/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.common.base.service;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.base.Strings;
import com.je.common.auth.impl.Department;
import com.je.common.auth.impl.RealOrganizationUser;
import com.je.common.auth.impl.account.Account;
import com.je.common.base.DynaBean;
import com.je.common.base.constants.ConstantVars;
import com.je.common.base.constants.tree.NodeType;
import com.je.common.base.constants.workflow.AudFlagStatus;
import com.je.common.base.db.JEDatabase;
import com.je.common.base.document.MetadataEnum;
import com.je.common.base.document.UploadTypeEnum;
import com.je.common.base.entity.ProductResult;
import com.je.common.base.entity.QueryInfo;
import com.je.common.base.entity.func.FuncInfo;
import com.je.common.base.entity.func.FuncRelation;
import com.je.common.base.entity.func.FuncRelationField;
import com.je.common.base.exception.PlatformException;
import com.je.common.base.exception.PlatformExceptionEnum;
import com.je.common.base.mapper.query.ConditionEnum;
import com.je.common.base.mapper.query.NativeQuery;
import com.je.common.base.mapper.query.Query;
import com.je.common.base.service.db.PcDBMethodServiceFactory;
import com.je.common.base.service.rpc.*;
import com.je.common.base.table.service.PCDataService;
import com.je.common.base.util.*;
import com.je.core.entity.extjs.JSONTreeNode;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.sql.Clob;
import java.text.DecimalFormat;
import java.util.*;

/**
 * 抽象实现通用处理
 */
public abstract class AbstractCommonService implements CommonService {

    public static final String FRONT_END_PK_VALUE_KEY = "__doInsertOldPkValue__";

    @Autowired
    public MetaService metaService;
    @Autowired
    private MetaResourceService metaResourceService;
    @Autowired
    public SystemVariableRpcService systemVariableService;
    @Autowired
    public PCDataService pcDataService;
    @Resource(name = "taskExecutor")
    private TaskExecutor taskExecutor;
    @Autowired
    private BeanService beanService;
    @Autowired
    private DocumentInternalRpcService documentInternalRpcService;
    @Autowired
    private FunInfoRpcService funInfoRpcService;
    @Autowired
    private CodeGenService codeGenService;
    @Autowired
    private QueryBuilderService queryBuilderService;
    @Autowired
    private SystemSettingRpcService systemSettingRpcService;
    @Autowired
    private BaseProductRpcService baseProductRpcService;
    @Autowired
    private BaseDevelopRpcService baseDevelopRpcService;
    @Autowired
    private MetaDataPermCheckService metaDataPermCheckService;

    private List<Map<String, Object>> loadLocalTreeItems(String sql) {
        return metaService.selectSql(sql);
    }

    @Override
    public boolean checkFuncMoreRoot(String funcCode) {
        if (!Strings.isNullOrEmpty(funcCode)) {
            FuncInfo funcInfo = functionConfig(funcCode);
            String treeFuncConfig = funcInfo.getTreeFuncConfig();
            if (!Strings.isNullOrEmpty(treeFuncConfig)) {
                JSONArray treeConfigArray = JSONArray.parseArray(treeFuncConfig);
                for (int i = 0; i < treeConfigArray.size(); i++) {
                    if (!"moreRoot".equals(treeConfigArray.getJSONObject(i).getString("key"))) {
                        continue;
                    }
                    String value = treeConfigArray.getJSONObject(i).getString("value");
                    if (Strings.isNullOrEmpty(value) || value.toUpperCase().equals("FALSE")) {
                        return false;
                    } else {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    @Override
    public String findSubFuncForeignField(String funcCode) {
        if (StringUtil.isEmpty(funcCode)) {
            return null;
        }
        DynaBean childeFuncInfo = metaResourceService.selectOne("JE_CORE_FUNCRELATION", NativeQuery.build()
                .eq("FUNCRELATION_CODE", funcCode)
                .eq("FUNCRELATION_ENABLED", "1")
                .eq("FUNCRELATION_RELYONTYPE", "func"), "JE_CORE_FUNCRELATION_ID,FUNCRELATION_FUNCINFO_ID,FUNCRELATION_TABLENAME");
        if (childeFuncInfo == null) {
            return null;
        }

        //子功能id
        String funcRelationId = childeFuncInfo.getStr("JE_CORE_FUNCRELATION_ID");
        //父功能id
        String funcRelationFuncinfoId = childeFuncInfo.getStr("FUNCRELATION_FUNCINFO_ID");
        DynaBean parentInfo = metaResourceService.selectOne("JE_CORE_FUNCINFO", NativeQuery.build().
                eq("JE_CORE_FUNCINFO_ID", funcRelationFuncinfoId), "FUNCINFO_PKNAME");
        if (parentInfo == null) {
            return null;
        }

        //父类
        String parentPkCode = parentInfo.getStr("FUNCINFO_PKNAME");
        DynaBean childWhereInfo = metaResourceService.selectOne("JE_CORE_ASSOCIATIONFIELD", NativeQuery.build()
                        .eq("ASSOCIATIONFIELD_FUNCRELAT_ID", funcRelationId)
                        .eq("ASSOCIATIONFIELD_PRIFIELDCODE", parentPkCode)
                        .eq("ASSOCIATIONFIELD_ASSOCIATION", "=")
                        .eq("ASSOCIATIONFIELD_TRANSMIT", "1"),
                "ASSOCIATIONFIELD_CHIFIELDCODE");
        if (childWhereInfo == null) {
            return null;
        }
        return childWhereInfo.getStr("ASSOCIATIONFIELD_CHIFIELDCODE");
    }

    @Override
    public DynaBean addFuncMoreRootNode(String funcCode, DynaBean dynaBean) {
        return addFuncMoreRootNode(funcCode, dynaBean, "");
    }

    @Override
    public DynaBean addFuncMoreRootNode(String funcCode, DynaBean dynaBean, String subFuncForeignKey) {
        String foreignKey = subFuncForeignKey;
        if (Strings.isNullOrEmpty(foreignKey)) {
            foreignKey = findSubFuncForeignField(funcCode);
        }
        String childUuid = JEUUID.uuid();
        DynaBean bean = new DynaBean(dynaBean.getTableCode(), true);
        //赋值外键
        bean.set(foreignKey, dynaBean.getStr(foreignKey));
        bean.set("SY_NODETYPE", NodeType.ROOT);
        bean.set("SY_LAYER", 0);
        bean.set("SY_PARENT", null);
        bean.set("SY_PATH", "/" + childUuid);
        bean.set("SY_ORDERINDEX", 1);
        bean.set("SY_TREEORDERINDEX", StringUtil.preFillUp("1", 6, '0'));
        bean.set(bean.getPkCode(), childUuid);
        buildModelCreateInfo(bean);
        metaService.insert(dynaBean.getTableCode(), bean);
        return bean;
    }

    @Override
    public List<JSONTreeNode> getLocalJsonTreeNodeList(String rootId, String tableName, JSONTreeNode template, QueryInfo queryInfo) {
        return getLocalJsonTreeNodeList(rootId, tableName, template, queryInfo, null, null);
    }

    @Override
    public List<JSONTreeNode> getLocalJsonTreeNodeList(String rootId, String tableName, JSONTreeNode template, QueryInfo queryInfo, List<String> includeIds, String[] beanFields) {
        List<JSONTreeNode> children = new ArrayList<JSONTreeNode>();
        if (TreeUtil.verify(template)) {
            String sql = PcDBMethodServiceFactory.getPcDBMethodService().getTreeSql(template, queryInfo, tableName, rootId);
            List<Map<String, Object>> treeItems = loadLocalTreeItems(sql);
            children = getJsonTreeNodeList(treeItems, template, includeIds, beanFields);
        }
        return children;
    }

    private List<JSONTreeNode> getJsonTreeNodeList(List<Map<String, Object>> treeItems, JSONTreeNode template, List<String> includeIds, String[] beanFields) {
        List<JSONTreeNode> children = new ArrayList<JSONTreeNode>();
        if (TreeUtil.verify(template)) {
            if (null != treeItems && 0 != treeItems.size()) {
                for (int i = 0; i < treeItems.size(); i++) {
                    Map<String, Object> record = treeItems.get(i);
                    JSONTreeNode node = new JSONTreeNode();
                    //主键
                    node.setId((String) record.get(template.getId()));
                    //名称
                    node.setText((String) record.get(template.getText()));
                    //编码
                    node.setCode((String) record.get(template.getCode()));
                    //父节点
                    node.setParent((String) record.get(template.getParent()));
                    //节点信息
                    if (StringUtil.isNotEmpty(template.getNodeInfo())) {
                        if (JEDatabase.getCurrentDatabase().equals(ConstantVars.STR_ORACLE) || JEDatabase.getCurrentDatabase().equals(ConstantVars.STR_SHENTONG)) {
                            node.setNodeInfo(StringUtil.getClobValue(record.get(template.getNodeInfo())));
                        } else {
                            node.setNodeInfo(record.get(template.getNodeInfo()) + "");
                        }
                    }
                    //节点信息类型
                    if (StringUtil.isNotEmpty(template.getNodeInfoType())) {
                        node.setNodeInfoType((String) record.get(template.getNodeInfoType()) + "");
                    }
                    //是否叶子
                    if (StringUtil.isNotEmpty(template.getNodeType())) {
                        if (NodeType.LEAF.equalsIgnoreCase(record.get(template.getNodeType()) + "")) {
                            node.setLeaf(true);
                        } else {
                            node.setLeaf(false);
                        }
                        node.setNodeType((String) record.get(template.getNodeType()) + "");
                    }
                    if (StringUtil.isNotEmpty(template.getLayer())) {
                        node.setLayer(record.get(template.getLayer()) + "");
                    }
                    //图标图片地址
                    if (StringUtil.isNotEmpty(template.getIcon())) {
                        node.setIcon(record.get(template.getIcon()) + "");
                    }
                    //图标样式
                    if (StringUtil.isNotEmpty(template.getIconColor())) {
                        node.setIconColor(record.get(template.getIconColor()) + "");
                    }
                    //是否禁用
                    if (StringUtil.isNotEmpty(template.getDisabled())) {
                        node.setDisabled(record.get(template.getDisabled()) + "");
                    } else {
                        node.setDisabled("0");
                    }
                    //树形路径
                    if (StringUtil.isNotEmpty(template.getNodePath())) {
                        node.setNodePath(record.get(template.getNodePath()) + "");
                    }
                    //描述
                    if (StringUtil.isNotEmpty(template.getDescription())) {
                        if (JEDatabase.getCurrentDatabase().equals(ConstantVars.STR_ORACLE) || JEDatabase.getCurrentDatabase().equals(ConstantVars.STR_SHENTONG)) {
                            node.setDescription(StringUtil.getClobValue(record.get(template.getDescription())));
                        } else {
                            node.setDescription(record.get(template.getDescription()) + "");
                        }
                    }
                    //排序
                    if (StringUtil.isNotEmpty(template.getOrderIndex())) {
                        node.setOrderIndex(record.get(template.getOrderIndex()) + "");
                    }
                    if (StringUtil.isNotEmpty(template.getTreeOrderIndex())) {
                        node.setTreeOrderIndex(record.get(template.getTreeOrderIndex()) + "");
                    }
                    if (beanFields != null && beanFields.length > 0) {
                        Map<String, Object> beanValues = new HashMap<String, Object>();
                        for (String fieldName : beanFields) {
                            beanValues.put(fieldName, record.get(fieldName));
                        }
                    }
                    //如果是oracle则单独处理
                    if (JEDatabase.getCurrentDatabase().equals(ConstantVars.STR_ORACLE) || JEDatabase.getCurrentDatabase().equals(ConstantVars.STR_ORACLE)) {
                        for (String key : record.keySet()) {
                            if (record.get(key) != null && record.get(key) instanceof Clob) {
                                record.put(key, StringUtil.getClobValue(record.get(key)));
                            }
                            if (record.get(key) == null) {
                                record.put(key, "");
                            }
                        }
                    }
                    node.setBean(record);
                    //排除指定节点
                    if (includeIds != null && includeIds.size() > 0) {
                        String nodeId = node.getId();
                        if (includeIds.contains(nodeId)) {
                            children.add(node);
                        }
                    } else {
                        children.add(node);
                    }
                }
            }
        }
        return children;
    }

    @Override
    @Transactional
    public String buildCode(String fieldCode, String funcCode, DynaBean dynaBean) {
        return buildCode(fieldCode, funcCode, dynaBean, SecurityUserHolder.getCurrentAccountTenantId());
    }

    @Override
    @Transactional
    public String buildCode(String fieldCode, String funcCode, DynaBean dynaBean, String tenantId) {
        DynaBean funcInfo = metaResourceService.selectOne("JE_CORE_FUNCINFO", NativeQuery.build().eq("FUNCINFO_FUNCCODE", funcCode).in("FUNCINFO_NODEINFOTYPE", "FUNC", "FUNCFIELD"), "FUNCINFO_FUNCNAME,FUNCINFO_FUNCCODE,JE_CORE_FUNCINFO_ID,FUNCINFO_TABLENAME");
        if (funcInfo == null) {
            return "";
        }
        DynaBean field = metaResourceService.selectOneByNativeQuery("JE_CORE_RESOURCEFIELD", NativeQuery.build().eq("RESOURCEFIELD_FUNCINFO_ID", funcInfo.getStr("JE_CORE_FUNCINFO_ID")).eq("RESOURCEFIELD_CODE", fieldCode));
        if (field == null) {
            return "";
        }
        String configInfoStr = field.getStr("RESOURCEFIELD_CONFIGINFO");
        if (StringUtil.isEmpty(configInfoStr)) {
            return "";
        }
        JSONObject infos = new JSONObject();
        String tableCode = funcInfo.getStr("FUNCINFO_TABLENAME", "");
        DynaBean table = beanService.getResourceTable(tableCode);
        infos.put("TABLECODE", tableCode);
        if (table != null) {
            infos.put("TABLENAME", table.getStr("RESOURCETABLE_TABLENAME"));
        }
        infos.put("FUNCID", funcInfo.getStr("JE_CORE_FUNCINFO_ID"));
        infos.put("FUNCCODE", funcCode);
        infos.put("FUNCNAME", funcInfo.getStr("FUNCINFO_FUNCNAME"));
        if (StringUtil.isNotEmpty(tenantId)) {
            infos.put("ZHID", tenantId);
        }
        return codeGenerator(JSON.parseArray(configInfoStr), dynaBean, fieldCode, infos);
    }

    @Override
    public void buildCode(String codeGenFieldInfo, DynaBean dynaBean) {
        buildCode(codeGenFieldInfo, dynaBean, SecurityUserHolder.getCurrentAccountTenantId());
    }

    @Override
    @Transactional
    public void buildCode(String codeGenFieldInfo, DynaBean dynaBean, String zhId) {
        JSONArray array = JSON.parseArray(codeGenFieldInfo);
        for (int i = 0; i < array.size(); i++) {
            JSONObject o = array.getJSONObject(i);
            String fieldName = o.getString("code");
            String funcId = o.getString("funcId");
            String funcCode = "";
            if (o.containsKey("funcCode")) {
                funcCode = o.getString("funcCode");
            }
            String tableCode = "";
            if (o.containsKey("tableCode")) {
                tableCode = o.getString("tableCode");
            }
            String tableName = "";
            if (StringUtil.isNotEmpty(tableCode)) {
                DynaBean table = beanService.getResourceTable(tableCode);
                tableName = table.getStr("RESOURCETABLE_TABLENAME");
            }
            String funcName = o.getString("funcName");
            JSONObject infos = new JSONObject();
            infos.put("FUNCID", funcId);
            infos.put("FUNCCODE", funcCode);
            infos.put("FUNCNAME", funcName);
            infos.put("TABLENAME", tableName);
            infos.put("TABLECODE", tableCode);
            if (StringUtil.isNotEmpty(zhId)) {
                infos.put("ZHID", zhId);
            }
            JSONArray codePatterns = o.getJSONArray("configInfo");
            if (StringUtil.isNotEmpty(fieldName) && StringUtil.isNotEmpty(funcId) && codePatterns != null && codePatterns.size() > 0) {
                String fieldCodeValue = codeGenerator(codePatterns, dynaBean, fieldName, infos);
                dynaBean.setStr(fieldName, fieldCodeValue);
            }
        }
    }

    @Transactional
    public String codeGenerator(JSONArray codePatterns, DynaBean entity, String fieldName, JSONObject infos) {
        StringBuffer codeValue = new StringBuffer();
        String zhId = "";
        //TODO 数据保存暂时没有存租户id 这里增加租户的话 会查不到数据
//        if (infos.containsKey("ZHID")) {
//            zhId = infos.getString("ZHID");
//        }
        for (int i = 0; i < codePatterns.size(); i++) {
            JSONObject codePattern = codePatterns.getJSONObject(i);
            //取值方式
            String qzfs = codePattern.getString("qzfs");
            //对应值
            String dyz = codePattern.getString("dyz");
            //截取格式
            String jq = codePattern.getString("jqws");
            //日期格式
            String gs = codePattern.getString("gs");
            //常量
            if ("CL".equals(qzfs)) {
                if (StringUtil.isNotEmpty(dyz)) {
                    codeValue.append(dyz);
                }
                //全局变量
            } else if ("QJBL".equals(qzfs)) {
                if (StringUtil.isNotEmpty(dyz) && StringUtil.isNotEmpty(systemVariableService.requireBackVariable(dyz))) {
                    codeValue.append(StringUtil.getSubValue(systemVariableService.requireBackVariable(dyz), jq));
                } else if (StringUtil.isNotEmpty(dyz) && StringUtil.isNotEmpty(StringUtil.codeToValue(dyz))) {
                    if (StringUtil.isNotEmpty(gs)) {
                        Date date = DateUtils.getDate(StringUtil.codeToValue(dyz), DateUtils.DAFAULT_DATETIME_FORMAT);
                        if (date == null) {
                            date = DateUtils.getDate(StringUtil.codeToValue(dyz), DateUtils.DAFAULT_DATE_FORMAT);
                        }
                        if (date != null) {
                            codeValue.append(StringUtil.getSubValue(DateUtils.formatDate(date, gs), jq));
                        }
                    } else {
                        codeValue.append(StringUtil.getSubValue(StringUtil.codeToValue(dyz), jq));
                    }
                }
            } else if ("BDZD".equals(qzfs)) {
                if (StringUtil.isNotEmpty(dyz) && StringUtil.isNotEmpty(entity.getStr(dyz, ""))) {
                    if (StringUtil.isNotEmpty(gs)) {
                        Date date = DateUtils.getDate(entity.getStr(dyz, ""), DateUtils.DAFAULT_DATETIME_FORMAT);
                        if (date == null) {
                            date = DateUtils.getDate(entity.getStr(dyz, ""), DateUtils.DAFAULT_DATE_FORMAT);
                        }
                        if (date != null) {
                            codeValue.append(StringUtil.getSubValue(DateUtils.formatDate(date, gs), jq));
                        }
                    } else {
                        codeValue.append(StringUtil.getSubValue(entity.getStr(dyz, ""), jq));
                    }
                }
            } else if ("LSH".equals(qzfs)) {
                //长度
                String cd = codePattern.getString("cd");
                //流水号基准
                String lshDyz = StringUtil.getDefaultValue(codePattern.getString("dyz") + "", "FUNC");
                //起始号
                String codeBase = codePattern.getString("qsh");
                //步长
                String step = codePattern.getString("bc");
                //周期
                String cycle = codePattern.getString("zq");
                if (!Strings.isNullOrEmpty(cd) && !Strings.isNullOrEmpty(codeBase)) {
                    int cdInt = Integer.parseInt(cd);
                    int codeBaseInt = codeBase.length();
                    if (cdInt < codeBaseInt) {
                        throw new PlatformException("流水号起始号长度不能大于流水号的长度！", PlatformExceptionEnum.UNKOWN_ERROR);
                    }
                }
                if (!"TABLE".equals(lshDyz)) {
                    lshDyz = "FUNC";
                }
                infos.put("TYPE", lshDyz);
                // && StringUtil.isNotEmpty(cycle)
                if (StringUtil.isNotEmpty(cd) && StringUtil.isNotEmpty(codeBase) && StringUtil.isNotEmpty(step)) {
                    //格式转换
                    JSONObject json = JSON.parseObject(infos.toJSONString());
                    if (StringUtil.isNotEmpty(zhId)) {
                        codeValue.append(codeGenService.getSeqByJtgsId(json, fieldName, codeBase, step, cycle, Integer.parseInt(cd), zhId));
                    } else {
                        codeValue.append(codeGenService.getSeq(json, fieldName, codeBase, step, cycle, Integer.parseInt(cd)));
                    }
                }
            }
        }
        return codeValue.toString();
    }

    @Override
    public void buildFuncDefaultValues(String funcCode, DynaBean dynaBean) {
        FuncInfo funcInfo = funInfoRpcService.getFuncInfo(funcCode);
        Map<String, String> fieldInfos = funcInfo.getFieldDefaultValues();
        for (String key : fieldInfos.keySet()) {
            String defaultVal = fieldInfos.get(key);
            defaultVal = StringUtil.codeToValue(defaultVal);
            dynaBean.set(key, defaultVal);
        }
    }

    @Override
    public void generateTreeOrderIndex(DynaBean dynaBean) {
        String parent = dynaBean.getStr("SY_PARENT");
        List<Map<String, Object>> objs;
        if (JEDatabase.getCurrentDatabase().equals(ConstantVars.STR_DM)) {
            objs = metaService.selectSql(ConditionsWrapper.builder(
                    "select MAX(SUBSTRING(SY_TREEORDERINDEX)) AS MAX,MAX(SUBSTRING(SY_ORDERINDEX)) SY_ORDERINDEX FROM " + dynaBean.getTableCode() + " WHERE SY_PARENT= {0}", parent));
        } else {
            objs = metaService.selectSql(ConditionsWrapper.builder(
                    "select MAX(SY_TREEORDERINDEX) AS MAX,MAX(SY_ORDERINDEX) SY_ORDERINDEX FROM " + dynaBean.getTableCode() + " WHERE SY_PARENT= {0}", parent));
        }
        List<Map<String, Object>> parentInfo = metaService.selectSql(ConditionsWrapper.builder(
                "select SY_TREEORDERINDEX  FROM " + dynaBean.getTableCode() + " WHERE " + dynaBean.getPkCode() + "= {0}", parent));
        if (objs != null && !objs.isEmpty() && objs.get(0) != null) {
            String maxValue = StringUtil.getDefaultValue(objs.get(0).get("MAX"), "");
            String orderIndex = StringUtil.getDefaultValue(objs.get(0).get("SY_ORDERINDEX"), "0");
            String treeOrderIndex = StringUtil.isEmpty(maxValue) ? StringUtil.getDefaultValue(parentInfo.get(0).get("SY_TREEORDERINDEX"), "") : buildTreeOrderIndex(maxValue, 1);
            dynaBean.setStr("SY_TREEORDERINDEX", treeOrderIndex);
            dynaBean.set("SY_ORDERINDEX", Integer.parseInt(orderIndex) + 1);
        } else {
            dynaBean.set("SY_ORDERINDEX", 1);
            String treeOrderIndex = StringUtil.getDefaultValue(parentInfo.get(0).get("SY_TREEORDERINDEX"), "");
            dynaBean.setStr("SY_TREEORDERINDEX", treeOrderIndex + "000001");
        }
    }

    private String buildTreeOrderIndex(String treeOrderIndex, int c) {
        String preTreeOrderInde = treeOrderIndex.substring(0, treeOrderIndex.length() - 6);
        String sufTreeOrderInde = treeOrderIndex.substring(treeOrderIndex.length() - 6);
        int i = Integer.parseInt(sufTreeOrderInde);
        DecimalFormat df = new DecimalFormat("000000");
        String lengthStr = "";
        lengthStr = df.format(i + c);
        return preTreeOrderInde + lengthStr;
    }

    @Override
    public void generateOrderIndex(DynaBean dynaBean, String wheresql) {
        if (StringUtil.isNotEmpty(wheresql)) {
            wheresql = " WHERE " + wheresql;
        }
        List<Map<String, Object>> objs;
        if (JEDatabase.getCurrentDatabase().equals(ConstantVars.STR_DM)) {
            objs = metaService.selectSql(ConditionsWrapper.builder("select MAX(SUBSTRING(SY_ORDERINDEX)) SY_ORDERINDEX FROM " + dynaBean.getTableCode() + wheresql));
        } else {
            objs = metaService.selectSql(ConditionsWrapper.builder("select MAX(SY_ORDERINDEX) SY_ORDERINDEX FROM " + dynaBean.getTableCode() + wheresql));
        }
        if (objs != null && objs.size() > 0) {
            Map<String, Object> map = objs.get(0);
            int index = map.get("SY_ORDERINDEX") == null ? 1 : (Integer.parseInt(map.get("SY_ORDERINDEX").toString())) + 1;
            dynaBean.set("SY_ORDERINDEX", index);
        } else {
            dynaBean.set("SY_ORDERINDEX", 1);
        }
    }

    private List<DynaBean> loadDynaBeanFieldNames4Select(DynaBean dynaBean) {
        //1.得到表的模型类
        DynaBean table = beanService.getResourceTable(dynaBean.getStr(BeanService.KEY_TABLE_CODE));
        if (table == null) {
            return null;
        }
        //2.为动态类组装select目标字段
        List<DynaBean> columns = table.getDynaBeanList(BeanService.KEY_TABLE_COLUMNS);
        StringBuilder fieldNames = new StringBuilder();
        for (DynaBean column : columns) {
            fieldNames.append(column.getStr("TABLECOLUMN_CODE") + ",");
        }
        if (fieldNames.length() > 0) {
            fieldNames.deleteCharAt(fieldNames.length() - 1);
        }
        dynaBean.set(BeanService.DEF_ALL_FIELDS, fieldNames.toString());
        return columns;
    }

    @Override
    public List<Map<String, Object>> loadTree(String rootId, String tableCode, String excludes, Boolean checked, QueryInfo queryInfo) {
        DynaBean table = beanService.getResourceTable(tableCode);
        JSONTreeNode template = beanService.buildJSONTreeNodeTemplate((List<DynaBean>) table.get(BeanService.KEY_TABLE_COLUMNS));
        List<Map<String, Object>> datas = loadTree(rootId, template, table, excludes, checked, queryInfo);
        Map<String, Object> root = buildJSONTree4Dyna(datas, table.getStr(BeanService.KEY_PK_CODE), template.getParent());
        List<Map<String, Object>> childrens = (List<Map<String, Object>>) root.get("children");
        return childrens;
    }

    @Override
    public List<Map<String, Object>> loadTree(String rootId, JSONTreeNode template, DynaBean dynaBean, QueryInfo queryInfo) {
        String tableName = dynaBean.getStr(BeanService.KEY_TABLE_CODE);
        List<DynaBean> columns = loadDynaBeanFieldNames4Select(dynaBean);
        //构建递归查询语句
        String sql = PcDBMethodServiceFactory.getPcDBMethodService().getDynaTreeSql(columns, template, tableName, rootId, queryInfo);
        List<Map<String, Object>> dynas = metaService.selectSql(sql);
        //递归查询出来List
        List<Map<String, Object>> datas = new ArrayList<>();
        for (Map<String, Object> obj : dynas) {
            Map<String, Object> item = new HashMap();
            for (int i = 0; i < columns.size(); i++) {
                DynaBean column = columns.get(i);
                item.put(column.getStr("TABLECOLUMN_CODE"), obj.get(column.getStr("TABLECOLUMN_CODE")));
            }
            item.put("children", new ArrayList<Map<String, Object>>());
            item.put("leaf", true);
            item.put("checked", false);
            datas.add(item);
        }
        //构建树形
        return datas;
    }

    @Override
    public List<Map<String, Object>> loadTree(String rootId, JSONTreeNode template, DynaBean table, String excludes, Boolean checked, QueryInfo queryInfo) {
        String tableName = table.getStr(BeanService.KEY_TABLE_CODE);
        List<DynaBean> columns = (List<DynaBean>) table.get(BeanService.KEY_TABLE_COLUMNS);
        String sql = PcDBMethodServiceFactory.getPcDBMethodService().getDynaTreeSql(columns, template, tableName, rootId, queryInfo);
        List<Map<String, Object>> dynas = metaService.selectSql(sql);
        List<Map<String, Object>> datas = new ArrayList<>();
        for (Map<String, Object> obj : dynas) {
            Map<String, Object> item = new HashMap();
            for (int i = 0; i < columns.size(); i++) {
                DynaBean column = columns.get(i);
                item.put(column.getStr("TABLECOLUMN_CODE"), obj.get(column.getStr("TABLECOLUMN_CODE")));
            }
            //"id","text","cls","leaf","href","hrefTarget","expandable","description","code","icon","iconCls","bigIcon","bigIconCls","parent","nodeInfo","nodeInfoType","disabled","nodePath"
            item.put("children", new ArrayList<HashMap>());
            item.put("id", item.get(template.getId()));
            item.put("text", item.get(template.getText()));
            item.put("code", item.get(template.getCode()));
            item.put("parent", item.get(template.getParent()));
            if (StringUtil.isNotEmpty(template.getNodeInfo())) {
                item.put("nodeInfo", item.get(template.getNodeInfo()));
            }
            if (StringUtil.isNotEmpty(template.getNodeInfoType())) {
                item.put("nodeInfoType", item.get(template.getNodeInfoType()));
            }
            if (StringUtil.isNotEmpty(template.getNodeType())) {
                item.put("nodeType", item.get(template.getNodeType()));
            }
            if (StringUtil.isNotEmpty(template.getIcon())) {
                item.put("icon", item.get(template.getIcon()));
            }
            if (StringUtil.isNotEmpty(template.getIconColor())) {
                item.put("iconColor", item.get(template.getIconColor()));
            }
            if (StringUtil.isNotEmpty(template.getLayer())) {
                item.put("layer", item.get(template.getLayer()));
            }
            if (StringUtil.isNotEmpty(template.getDisabled())) {
                item.put("disabled", item.get(template.getDisabled()));
            }
            if (StringUtil.isNotEmpty(template.getNodePath())) {
                item.put("nodePath", item.get(template.getNodePath()));
            }
            if (StringUtil.isNotEmpty(template.getDescription())) {
                item.put("description", item.get(template.getDescription()));
            }
            if (StringUtil.isNotEmpty(template.getOrderIndex())) {
                item.put("orderIndex", item.get(template.getOrderIndex()));
            }
            item.put("checked", checked);
            item.put("leaf", true);
            item.put("children", new ArrayList<HashMap>());
            for (String exclude : excludes.split(",")) {
                item.remove(exclude);
            }
            //如果是oracle则单独处理
            if (JEDatabase.getCurrentDatabase().equals(ConstantVars.STR_ORACLE)
                    || JEDatabase.getCurrentDatabase().equals(ConstantVars.STR_SHENTONG)) {
                for (Object key : item.keySet()) {
                    if (item.get(key + "") != null && item.get(key + "") instanceof Clob) {
                        item.put(key + "", StringUtil.getClobValue(item.get(key + "")));
                    }
                }
            }
            datas.add(item);
        }
        return datas;
    }

    @Override
    public JSONTreeNode buildJSONNewTree(List<JSONTreeNode> lists, String rootId) {
        JSONTreeNode root = TreeUtil.buildRootNode();
        //当前循环这个集合每一个元素
        for (JSONTreeNode node : lists) {
            if (node.getParent() == null || "".equals(node.getParent()) || node.getId().equals(rootId)) {
                root = node;
                lists.remove(node);
                break;
            }
        }
        createTreeChildren(lists, root);
        return root;
    }

    public void createTreeChildren(List<JSONTreeNode> childrens, JSONTreeNode root) {
        String parentId = root.getId();
        for (int i = 0; i < childrens.size(); i++) {
            JSONTreeNode node = childrens.get(i);
            if (parentId.equals(node.getParent())) {
                root.getChildren().add(node);
                //当前不能删除节点，因为孩子引用与它， 递归回来，坐标失效
                createTreeChildren(childrens, node);
            }
            if (i == childrens.size() - 1) {
                if (root.getChildren().size() > 0) {
                    root.setLeaf(false);
                }
                return;
            }
        }
    }

    /**
     * list转树形
     *
     * @param lists
     * @param pkCode
     * @param parentCode
     */
    public Map<String, Object> buildJSONTree4Dyna(List<Map<String, Object>> lists, String pkCode, String parentCode) {
        Map<String, Object> root = new HashMap<>();
        //当前循环这个集合每一个元素
        for (Map<String, Object> node : lists) {
            if (node.get(parentCode) == null || node.get(parentCode).equals("")) {
                root = node;
                lists.remove(node);
                break;
            }
        }
        createTreeChildren(lists, root, pkCode, parentCode);
        return root;
    }

    /**
     * 递归构建树形数据
     *
     * @param childrens
     * @param root
     * @param pkCode
     * @param parentCode
     */
    protected void createTreeChildren(List<Map<String, Object>> childrens, Map<String, Object> root, String pkCode, String parentCode) {
        String parentId = (String) root.get(pkCode);
        for (int i = 0; i < childrens.size(); i++) {
            Map<String, Object> node = childrens.get(i);
            if (node.get(parentCode) != null) {
                if (node.get(parentCode).toString().equalsIgnoreCase(parentId)) {
                    ((List<Map>) root.get("children")).add(node);
                    if (((List<Map>) root.get("children")).size() > 0) {
                        root.put("leaf", false);
                    }
                    //当前不能删除节点，因为孩子引用与它， 递归回来，坐标失效
                    createTreeChildren(childrens, node, pkCode, parentCode);
                }
                if (i == childrens.size() - 1) {
                    return;
                }
            }
        }
    }

    /**
     * 删除批量附件处理
     *
     * @param tableCode 表code
     * @param ids
     */
    @Override
    @Transactional
    public void doRemoveBatchFiles(String tableCode, String ids) {
        taskExecutor.execute(() -> {
            //删除文件
            documentInternalRpcService.deleteFiles(tableCode, ids, SecurityUserHolder.getCurrentAccountRealUser().getId());
        });
    }

    /**
     * 删除树形批量附件处理
     *
     * @param tableCode 表code
     * @param ids
     */
    @Override
    @Transactional
    public void doRemoveTreeBatchFiles(String tableCode, String ids) {
        //业务主键集合
        List<String> pkValues = new ArrayList<>();
        for (String id : ids.split(",")) {
            //获取主键字段名
            String pkCode = beanService.getPKeyFieldNamesByTableCode(tableCode);
            //查询业务数据主键集合
            List<DynaBean> busBeans = metaService.select(tableCode, ConditionsWrapper.builder().like("SY_PATH", id));
            for (DynaBean bean : busBeans) {
                pkValues.add(bean.getStr(pkCode));
            }
        }

        taskExecutor.execute(() -> {
            //删除文件
            documentInternalRpcService.deleteFiles(tableCode, ArrayUtils.join(pkValues), SecurityUserHolder.getCurrentAccountRealUserId());
        });
    }

    /**
     * 判断是否有子功能需级联删除
     *
     * @param funcInfo 功能对象
     */
    @Transactional
    public Boolean decideDeleteChildren(FuncInfo funcInfo) {
        List<FuncRelation> childrens = funcInfo.getChildren();
        for (FuncRelation children : childrens) {
            if (ArrayUtils.contains(new String[]{"func", "tree", "childfuncfield"}, children.getType())) {
                List<FuncRelationField> relatedFields = children.getChildFields();
                List<FuncRelationField> delRelatedFields = new ArrayList<>();
                //遍历主子关联字段
                for (FuncRelationField childField : relatedFields) {
                    //找到需要级联删除的字段
                    if (childField.getDeleteChild()) {
                        delRelatedFields.add(childField);
                    }
                }
                if (delRelatedFields.size() == 0) {
                    continue;
                }
                return true;
            }
        }
        return false;
    }

    /**
     * 文件保存业务元数据信息
     *
     * @param dynaBean         业务bean
     * @param batchFilesFields 多附件字段名
     * @param uploadableFields 单附件字段名
     * @param funcCode         功能编码
     * @return void
     */
    @Override
    @Transactional
    public void doSaveFileMetadata(DynaBean dynaBean, String batchFilesFields, String uploadableFields, String funcCode) {

        //无附件字段  跳过逻辑
        if (StringUtil.isEmpty(batchFilesFields) && StringUtil.isEmpty(uploadableFields)) {
            return;
        }

        //获取表名
        String tableCode = dynaBean.getTableCode();
        //获取主键字段名
        String pkCode = dynaBean.getPkCode();
        //设置主键，因为传过来的DynaBean可能是未设置主键的
        String pkValue = dynaBean.getPkValue();
        if (StringUtil.isEmpty(pkValue)) {
            throw new PlatformException("主键保存后未生成", PlatformExceptionEnum.UNKOWN_ERROR);
        }

        String userId = SecurityUserHolder.getCurrentAccountRealUserId();

        //遍历多附件字段信息
        if (StringUtil.isNotEmpty(batchFilesFields)) {
            for (String fieldCode : batchFilesFields.split(",")) {

                if (StringUtils.isBlank(dynaBean.getStr(fieldCode))) {
                    continue;
                }
                //组装元数据信息
                JSONObject metadataObject = new JSONObject();
                metadataObject.put(MetadataEnum.tableCode.getCode(), tableCode);
                metadataObject.put(MetadataEnum.pkValue.getCode(), pkValue);
                metadataObject.put(MetadataEnum.funcCode.getCode(), funcCode);
                metadataObject.put(MetadataEnum.uploadType.getCode(), UploadTypeEnum.FORM.getCode());
                metadataObject.put(MetadataEnum.tenantId.getCode(), SecurityUserHolder.getCurrentAccountTenantId());
                //设置元数据字段名
                metadataObject.put(MetadataEnum.fieldCode.getCode(), fieldCode);

                //获取字段中附件集合
                JSONArray files = JSONArray.parseArray(StringUtil.getDefaultValue(dynaBean.getStr(fieldCode), "[]"));
                //记录有效key
                List<String> usedFileKey = new ArrayList<>();
                //遍历附件
                for (Integer i = 0; i < files.size(); i++) {
                    JSONObject fileObj = files.getJSONObject(i);
                    //获取文件key
                    String fileKey = fileObj.getString("path");
                    usedFileKey.add(fileKey);
                }
                taskExecutor.execute(() -> {
                    //保存文件元数据
                    documentInternalRpcService.saveFileMetadataWithFileKeys(userId, metadataObject, usedFileKey);
                    //清理字段相关附件信息
                    documentInternalRpcService.updateFiledFile(userId, tableCode, pkValue, fieldCode, usedFileKey);
                });
            }
        }
        //遍历单附件字段信息
        if (StringUtil.isNotEmpty(uploadableFields)) {
            for (String fieldCode : uploadableFields.split(",")) {

                if (StringUtils.isBlank(dynaBean.getStr(fieldCode))) {
                    continue;
                }
                //组装元数据信息
                JSONObject metadataObject = new JSONObject();
                metadataObject.put(MetadataEnum.tableCode.getCode(), tableCode);
                metadataObject.put(MetadataEnum.pkValue.getCode(), pkValue);
                metadataObject.put(MetadataEnum.funcCode.getCode(), funcCode);
                metadataObject.put(MetadataEnum.uploadType.getCode(), UploadTypeEnum.FORM.getCode());
                metadataObject.put(MetadataEnum.tenantId.getCode(), SecurityUserHolder.getCurrentAccountTenantId());
                //设置元数据字段名
                metadataObject.put(MetadataEnum.fieldCode.getCode(), fieldCode);
                //记录有效key
                List<String> usedFileKey = new ArrayList<>();
                //获取文件key
                String value = StringUtil.getDefaultValue(dynaBean.getStr(fieldCode));
                if (StringUtil.isNotEmpty(value) && value.contains("*")) {
                    String[] fileMsg = value.split("\\*");
                    usedFileKey.add(fileMsg[fileMsg.length - 1]);
                }

                taskExecutor.execute(() -> {
                    //保存文件元数据
                    documentInternalRpcService.saveFileMetadataWithFileKeys(userId, metadataObject, usedFileKey);
                    //清理字段相关附件信息
                    documentInternalRpcService.updateFiledFile(userId, tableCode, pkValue, fieldCode, usedFileKey);
                });
            }
        }

    }

    @Override
    public void buildModelCreateInfo(DynaBean model) {
        buildModelCreateInfo(model, SecurityUserHolder.getCurrentAccount());
    }

    @Override
    public void buildModelCreateInfo(DynaBean model, Account currentAccount) {
        if (currentAccount != null) {
            RealOrganizationUser realOrganizationUser = currentAccount.getRealUser();
            //如果前台传入登录人信息则不构建，以后去掉
            if (realOrganizationUser != null) {
                model.put("SY_CREATEUSERID", realOrganizationUser.getId());
                model.put("SY_CREATEUSERNAME", realOrganizationUser.getName());
            }

            if (realOrganizationUser != null && realOrganizationUser.getOrganization() != null) {
                model.put("SY_CREATEORGID", realOrganizationUser.getOrganization().getId());
                model.put("SY_CREATEORGNAME", realOrganizationUser.getOrganization().getName());
                //如果是部门类型的机构
                if (realOrganizationUser.getOrganization() instanceof Department) {
                    Department department = (Department) realOrganizationUser.getOrganization();
                    if (!model.containsKey("SY_GROUP_COMPANY_ID") || Strings.isNullOrEmpty(model.getStr("SY_GROUP_COMPANY_ID"))) {
                        model.put("SY_GROUP_COMPANY_ID", department.getGroupCompanyId());
                        model.put("SY_GROUP_COMPANY_NAME", department.getGroupCompanyName());
                    }
                    if (!model.containsKey("SY_COMPANY_ID") || Strings.isNullOrEmpty(model.getStr("SY_COMPANY_ID"))) {
                        model.put("SY_COMPANY_ID", department.getCompanyId());
                        model.put("SY_COMPANY_NAME", department.getCompanyName());
                    }
                }
            }

            if (!model.containsKey("SY_ORG_ID") || Strings.isNullOrEmpty(model.getStr("SY_ORG_ID"))) {
                //机构ID
                model.put("SY_ORG_ID", currentAccount.getPlatformOrganization() == null ? "" : currentAccount.getPlatformOrganization().getId());
            }

            //租户
            if (!model.containsKey("SY_TENANT_ID") || Strings.isNullOrEmpty(model.getStr("SY_TENANT_ID"))) {
                model.put("SY_TENANT_ID", currentAccount.getTenantId());
                model.put("SY_TENANT_NAME", currentAccount.getTenantName());
            }

            //创建时间
            model.put("SY_CREATETIME", DateUtils.formatDateTime(new Date()));
        }

        //如果包含流程字段，则设置流程字段初始信息
        if (model.containsKey("SY_AUDFLAG") && Strings.isNullOrEmpty(model.getStr("SY_AUDFLAG"))) {
            model.put("SY_AUDFLAG", AudFlagStatus.NOSTATUS);
        }
        if (model.containsKey("SY_PDID") && Strings.isNullOrEmpty(model.getStr("SY_PDID"))) {
            model.put("SY_PDID", "");
        }
        if (model.containsKey("SY_PIID") && Strings.isNullOrEmpty(model.getStr("SY_PIID"))) {
            model.put("SY_PIID", "");
        }
    }

    @Override
    public void buildModelModifyInfo(DynaBean model) {
        buildModelModifyInfo(model, SecurityUserHolder.getCurrentAccount());
    }

    @Override
    public void buildModelModifyInfo(DynaBean model, Account currentAccount) {
        if (currentAccount == null) {
            return;
        }
        //校验
        RealOrganizationUser realOrganizationUser = currentAccount.getRealUser();
        //如果前台传入登录人信息则不构建，以后去掉
        if (realOrganizationUser != null) {
            model.put("SY_MODIFYUSERID", realOrganizationUser.getId());
            model.put("SY_MODIFYUSERNAME", realOrganizationUser.getName());
        }
        if (realOrganizationUser != null && realOrganizationUser.getOrganization() != null && StringUtil.isEmpty(model.get("SY_CREATEORG"))) {
            model.put("SY_MODIFYORGID", realOrganizationUser.getOrganization().getId());
            model.put("SY_MODIFYORGNAME", realOrganizationUser.getOrganization().getName());
        }
        model.put("SY_MODIFYTIME", DateUtils.formatDateTime(new Date()));
    }

    @Override
    public String buildOrderSql(String sort, String orderSql, String useOrderSql) {
        StringBuffer order = new StringBuffer();
        if (StringUtil.isNotEmpty(sort) && !StringUtil.EMPTY_JSON_ARRAY.equalsIgnoreCase(sort)) {
            String orderBy = buildSortOrder(sort, "");
            order.append(StringUtil.BLANK_SPACE);
            order.append(orderBy);
            if (StringUtil.isNotEmpty(orderSql) && "1".equals(useOrderSql)) {
                order.append(orderSql.trim().replace("order by", ",").replace("ORDER BY", ","));
            }
        } else if (StringUtil.isNotEmpty(orderSql)) {
            order.append(StringUtil.BLANK_SPACE);
            order.append(orderSql);
        }
        return order.toString();
    }

    @Override
    public String buildSortOrder(String sort, String excludes) {
        StringBuffer orderBy = new StringBuffer();
        String[] excludesArray = excludes.split(",");
        if (StringUtil.isNotEmpty(sort)) {
            JSONArray orderArray = JSON.parseArray(sort);
            if (null != orderArray && 0 != orderArray.size()) {
                Iterator<?> itor = orderArray.iterator();
                while (itor.hasNext()) {
                    net.sf.json.JSONObject obj = (net.sf.json.JSONObject) itor.next();
                    if (ArrayUtils.contains(excludesArray, obj.getString("property"))) {
                        continue;
                    }
                    orderBy.append(StringUtil.BLANK_SPACE + obj.getString("property"));
                    orderBy.append(StringUtil.BLANK_SPACE + obj.getString("direction"));
                    if (itor.hasNext()) {
                        orderBy.append(ArrayUtils.SPLIT);
                    }
                }
                if (orderBy.length() > 0) {
                    orderBy.insert(0, " ORDER BY ");
                }
            }
        }
        return orderBy.toString();
    }

    @Override
    public void buildResourceTable(DynaBean dynaBean) {
        DynaBean parentTable = this.metaService.selectOneByPk("JE_CORE_RESOURCETABLE", dynaBean.getStr("SY_PARENT"));
        if (!StringUtil.isEmpty(dynaBean.get("RESOURCETABLE_TYPE"))) {
            if ("MODULE".equals(dynaBean.get("RESOURCETABLE_TYPE"))) {
                dynaBean.set("SY_NODETYPE", "GENERAL");
            } else {
                dynaBean.set("SY_NODETYPE", "LEAF");
            }
        }
        dynaBean.set("SY_JECORE", "0");
        dynaBean.set("SY_JESYS", "1");
        dynaBean.put("RESOURCETABLE_ISCREATE", 0);
        dynaBean.put("RESOURCETABLE_ISUSEFOREIGNKEY", 0);
        dynaBean.put("RESOURCETABLE_MOREROOT", 0);
        dynaBean.put("SY_LAYER", parentTable.getInt("SY_LAYER") + 1);
        dynaBean.put("SY_DISABLED", 0);
        dynaBean.put("SY_PATH", parentTable.get("SY_PATH") + "/" + dynaBean.getStr("JE_CORE_RESOURCETABLE_ID"));
        dynaBean.put("SY_PARENTPATH", parentTable.get("SY_PATH"));
        generateTreeOrderIndex(dynaBean);
    }

    @Override
    public Boolean checkFieldUnique(DynaBean dynaBean, String fieldCode) {
        return checkFieldUnique(dynaBean, fieldCode, new Query());
    }

    @Override
    public Boolean checkFieldUnique(DynaBean dynaBean, String fieldCode, Query query) {
        String tableCode = dynaBean.getTableCode();
        if (StringUtil.isEmpty(tableCode) || StringUtil.isEmpty(fieldCode)) {
            return false;
        }

        if (StringUtil.isNotEmpty(dynaBean.getPkValue())) {
            query.addCustom(dynaBean.getPkCode(), ConditionEnum.NE, dynaBean.getPkValue());
        }
        //添加字段唯一性校验条件
        query.addCustom(fieldCode, ConditionEnum.EQ, dynaBean.getStr(fieldCode));
        //构建where条件
        ConditionsWrapper queryWrapper = query.buildWrapper();

        //构建count语句  并加入where条件
        ConditionsWrapper countWrapper = ConditionsWrapper.builder()
                .putAll(queryWrapper.getParameter())
                .apply(String.format("select * from %s where ", queryBuilderService.trimBlank(tableCode)))
                .apply(queryWrapper.getSql());
        List<Map<String, Object>> list = metaService.selectSql(countWrapper);
        return list.size() <= 0;
    }

    @Override
    @Transactional
    public void doChildrenTree(DynaBean dynaBean, String funcCode) {
        if (StringUtil.isEmpty(funcCode)) {
            return;
        }
        FuncInfo funcInfo = funInfoRpcService.getFuncInfo(funcCode);
        String mainPkCode = dynaBean.getPkCode();
        HashSet<Object> tableCodes = new HashSet<>();
        //子功能集合
        List<FuncRelation> childrenList = funcInfo.getChildren();
        for (int i = 0; i < childrenList.size(); i++) {
            FuncRelation children = childrenList.get(i);
            //子功能类型
            String funcType = children.getType();
            //表名
            String tableName = children.getTableCode();
            //满足 (树形子功能 || 自定义表名的甘特图子功能) 则按照多根树操作
            if ("tree".equalsIgnoreCase(funcType)) {
                if (StringUtils.isBlank(tableName)) {
                    throw new PlatformException("子功能 [" + children.getName() + "] 未配置表名", PlatformExceptionEnum.UNKOWN_ERROR);
                }
                //如果已经增加过则不处理
                if (tableCodes.contains(tableName)) {
                    continue;
                }

                String childPkCode = "";
                //取出外键的名称
                List<FuncRelationField> relatedFields = children.getChildFields();
                for (int j = 0; j < relatedFields.size(); j++) {
                    FuncRelationField childField = relatedFields.get(j);
                    if (childField.getFieldCode().equals(mainPkCode)) {
                        childPkCode = childField.getChildFieldCode();
                        break;
                    }
                }
                if (StringUtils.isBlank(childPkCode)) {
                    throw new PlatformException("子功能 [" + children.getName() + "] 缺少主功能主键字段配置", PlatformExceptionEnum.UNKOWN_ERROR);
                }
                String childUuid = JEUUID.uuid();
                DynaBean bean = new DynaBean(tableName, true);
                //赋值外键
                bean.set(childPkCode, dynaBean.getStr(mainPkCode));
                bean.set("SY_NODETYPE", NodeType.ROOT);
                bean.set("SY_LAYER", 0);
                bean.set("SY_PARENT", null);
                bean.set("SY_PATH", "/" + childUuid);
                bean.set("SY_ORDERINDEX", 1);
                bean.set("SY_TREEORDERINDEX", StringUtil.preFillUp("1", 6, '0'));
                bean.set(bean.getPkCode(), childUuid);
                buildModelCreateInfo(bean);
                metaService.insert(tableName, bean);
                tableCodes.add(tableName);
            }
        }
    }

    @Override
    public void buildProductQuery(Query jquery) {
        buildProductQuery(jquery, "SY_PRODUCT_ID");
    }

    @Override
    public void buildProductWrapper(ConditionsWrapper wrapper) {
        buildProductWrapper(wrapper, "SY_PRODUCT_ID");
    }

    @Override
    public void buildProductQuery(Query jquery, String column) {
        ProductResult result = baseDevelopRpcService.platform(SecurityUserHolder.getCurrentAccountId());
        if (result.isDevelop()) {
            List<String> platformProductList = baseProductRpcService.findPlatformProductIds();
            if (platformProductList != null && !platformProductList.isEmpty()) {
                result.getProducts().addAll(platformProductList);
            }
        }
        if (result.getProducts() != null && !result.getProducts().isEmpty()) {
            jquery.addCustom(column, ConditionEnum.IN, result.getProducts());
        }
    }

    @Override
    public void buildProductWrapper(ConditionsWrapper wrapper, String column) {
        ProductResult result = baseDevelopRpcService.platform(SecurityUserHolder.getCurrentAccountId());
        if (result.isDevelop()) {
            List<String> platformProductList = baseProductRpcService.findPlatformProductIds();
            if (platformProductList != null && !platformProductList.isEmpty()) {
                result.getProducts().addAll(platformProductList);
            }
        }
        if (result.getProducts() != null && !result.getProducts().isEmpty()) {
            wrapper.in(column, result.getProducts());
        }
    }

    @Override
    public boolean validDynaBeanUpdatePerm(String funcCode, String tableCode, String pkCode, String pkValue) {
        if (!Strings.isNullOrEmpty(funcCode)) {
            DynaBean originalBean = metaService.selectOneByPk(tableCode, pkValue);
            if (!metaDataPermCheckService.validUpdatePermission(funcCode, originalBean)) {
                return false;
            }
        }
        return true;
    }

    @Override
    public boolean validDynaBeanListUpdatePerm(String funcCode, String tableCode, ConditionsWrapper wrapper) {
        if (!Strings.isNullOrEmpty(funcCode)) {
            List<DynaBean> originalBeanList = metaService.select(tableCode, wrapper);
            for (DynaBean eachOriginalBean : originalBeanList) {
                if (!metaDataPermCheckService.validUpdatePermission(funcCode, eachOriginalBean)) {
                    return false;
                }
            }
        }
        return true;
    }

    @Override
    public boolean validDynaBeanDeletePerm(String funcCode, String tableCode, String pkCode, String pkValue) {
        if (!Strings.isNullOrEmpty(funcCode)) {
            DynaBean originalBean = metaService.selectOneByPk(tableCode, pkValue);
            if (!metaDataPermCheckService.validDeletePermission(funcCode, originalBean)) {
                return false;
            }
        }
        return true;
    }

    @Override
    public boolean validDynaBeanListDeletePerm(String funcCode, String tableCode, ConditionsWrapper wrapper) {
        if (!Strings.isNullOrEmpty(funcCode)) {
            List<DynaBean> originalBeanList = metaService.select(tableCode, wrapper);
            for (DynaBean eachOriginalBean : originalBeanList) {
                if (!metaDataPermCheckService.validDeletePermission(funcCode, eachOriginalBean)) {
                    return false;
                }
            }
        }
        return true;
    }

    @Override
    public String getModelCreateListInsertId(DynaBean model) {
        String pkCode = model.getPkCode();
        if (Strings.isNullOrEmpty(pkCode)) {
            return "";
        }
        String frontEndPkValue = model.getPkValue();
        model.set(model.getPkCode(), "");
        return frontEndPkValue;
    }

}
